/*
 * Timeset.cpp
 *
 *  Created on: 27.07.2012
 *      Author: maikel
 */

#include "Timeset.h"

#include <istream>
#include <string>
#include <sstream>
#include <limits>

using namespace std;


namespace gro {

istream &operator>>(istream &is, Timeset &ts) {
	string line;
	istringstream iss;

	// remember start position
	streampos start = is.tellg();

	// get title line, no time present, error
	getline(is, line);
	size_t found;
	if ((found = line.find("t=")) != string::npos) {
		ts.title = line.substr(0, found);
		iss.str(line.substr(found+2));
		iss >> ts.time;
	} else {
		is.seekg(start);
		throw Timeset::NoTime(line);
	}

	// count amount of atoms
	int N;
	if (is >> N) {
		is.ignore(numeric_limits<streamsize>::max(), '\n');
	} else {
		is.clear();
		is.seekg(start);
		is.setstate(ios::failbit);
		throw Timeset::ParseError(Timeset::atom_count);
	}

	// get all atoms
	ts.atoms.clear();
	for (int i = 0; i < N; i++) {
		Atom atom;
		if (!(is >> atom)) {
			is.clear();
			is.seekg(start);
			is.setstate(ios::failbit);
			throw Timeset::ParseError(Timeset::atom);
		}
		ts.atoms.push_back(atom);
	}

	// get box coordinates
	double box[3][3] = {0};
	for (int i = 0; i < 3; i++)
		is >> box[i][i];
	if (is.bad()) {
		is.clear();
		is.seekg(start);
		is.setstate(ios::failbit);
		throw Timeset::ParseError(Timeset::box_vector);
	}
	char c = is.get();
	if (c != '\n' && c != '\r') {
		is.putback(c);
		for (int i = 0; i < 3; i++)
				is >> box[i][(i+1)%3];
		for (int i = 0; i < 3; i++)
				is >> box[i][(i+2)%3];
	} else if (c == '\r') {
		is.get();
	}
	if (is.bad() && !is.eof()) {
		is.clear();
		is.seekg(start);
		is.setstate(ios::failbit);
		throw Timeset::ParseError(Timeset::box_vector);
	}
	memcpy(ts.box, box, sizeof(box));

	return is;
}

} /* namespace gro */
